﻿using ModbusProtocol;
using System;
using System.Collections.Generic;
using AutomaticScrewLocking.domain.modbus.comm.model.entity;
using AutomaticScrewLocking.domain.modbus.comm.model.valobj;

namespace AutomaticScrewLocking.domain.modbus.comm.service.impl
{
    public class PlcCommunicationServiceImpl : PlcCommunicationService
    {
        private ModbusTCP modbusTCP;
        private PlcParam plcParam;

        public PlcCommunicationServiceImpl(PlcParam pclParam)
        {
            this.modbusTCP = new ModbusTCP();
            this.plcParam = pclParam;
        }

        /// <summary>
        /// 连接PLC
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool ConnectPlc(out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                result = modbusTCP.Connect(plcParam.plcIp, plcParam.plcPort, out errorMsg);

            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }


            return result;
        }

        /// <summary>
        /// 断开PLC
        /// </summary>c
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool DisConnectPlc(out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                result = modbusTCP.DisConnect(out errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 读取保持寄存器开始信号
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public int ReadStartSignal(out bool result, out string errorMsg)
        {
            result = false;
            int leftRightVal = (UInt16)0;
            errorMsg = string.Empty;
            try
            {

                byte[] bytes = modbusTCP.ReadHoldRegister_Byte(plcParam.slaveAddress, (ushort)PlcAddress.startSignal, 1, out result, out errorMsg);
                if (result && bytes != null)
                {
                    byte[] startSingnalBytes = new byte[2];
                    Array.Copy(bytes, 0, startSingnalBytes, 0, 2);
                    ushort[] val = ConvertByteArrayToShortArray(startSingnalBytes);
                    leftRightVal = val[0];
                    result = true;
                }
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }
            return leftRightVal;
        }

        /// <summary>
        /// 读取保持寄存器结束信号
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public int ReadEndSignal(out bool result, out string errorMsg)
        {
            result = false;
            int value = (UInt16)0;
            errorMsg = string.Empty;
            try
            {
                byte[] bytes = modbusTCP.ReadHoldRegister_Byte(plcParam.slaveAddress, (ushort)PlcAddress.endSignal, 1, out result, out errorMsg);
                if (result && bytes != null)
                {
                    byte[] endSingnalBytes = new byte[2];
                    Array.Copy(bytes, 0, endSingnalBytes, 0, 2);
                    ushort[] val = ConvertByteArrayToShortArray(endSingnalBytes);
                    value = val[0];
                    result = true;
                }
            }
            catch (Exception ex)
            {
                result = false;
                errorMsg = ex.Message;
            }
            return value;
        }

        /// <summary>
        /// 写保持寄存器开始信号
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool writeStartSignal(out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                result = modbusTCP.WriteSingleHoldRegister(plcParam.slaveAddress, (ushort)PlcAddress.startSignal, 2, out errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 写保持寄存器结束信号
        /// </summary>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool WriteEndSignal(out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                result = modbusTCP.WriteSingleHoldRegister(plcParam.slaveAddress, (ushort)PlcAddress.endSignal, 2, out errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }

            return result;
        }

        /// <summary>
        /// 设置锁付开始Z轴位置
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool WriteStartPosZ(float pos, out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                byte[] writeBytes = BitConverter.GetBytes(pos);
                byte[] reverseBytes = DisplayData.ConvertData(writeBytes, DataFormat.FLOAT_CDAB, BitConverter.IsLittleEndian);
                result = modbusTCP.WriteMulitpleHoldRegister_Byte(plcParam.slaveAddress, (ushort)PlcAddress.screwStartPos, reverseBytes, out errorMsg);

            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }
            return result;
        }

        /// <summary>
        ///  设置锁付结束Z轴位置
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool WriteEndPosZ(float pos, out string errorMsg)
        {
            bool result = false;
            errorMsg = string.Empty;
            try
            {
                byte[] writeBytes = BitConverter.GetBytes(pos);
                byte[] reverseBytes = DisplayData.ConvertData(writeBytes, DataFormat.FLOAT_CDAB, BitConverter.IsLittleEndian);
                result = modbusTCP.WriteMulitpleHoldRegister_Byte(plcParam.slaveAddress, (ushort)PlcAddress.screwEndPos, reverseBytes, out errorMsg);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message;
            }
            return result;
        }

        /// <summary>
        /// 将字节数组转成uint16数组
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        private ushort[] ConvertByteArrayToShortArray(byte[] bytes)
        {
            List<ushort> list = new List<ushort>();
            int bytesNums = bytes.Length;
            for (int i = (UInt16)0; i < bytesNums; i = i + 2)
            {
                byte[] byteArray = new byte[2];
                byteArray[1] = bytes[i];//高位字节在左
                byteArray[0] = bytes[i + 1];
                ushort value = BitConverter.ToUInt16(byteArray, 0);
                list.Add(value);
            }
            return list.ToArray();
        }
    }
}
